package com.ifast.face.service.run;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import com.google.gson.Gson;
import com.ifast.face.dto.FaceSearchResult;
import com.ifast.face.service.FaceEngineService;
import com.ifast.websocket.OldWebSocketServer;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
/**
 * 
 * @author shíQíang㊚
 *
 */
@Slf4j
public class FaceRun implements Runnable {

	private LinkedBlockingQueue<BufferedImage> queue;// 阻塞队列 
	private String groupType;
	private FaceEngineService faceEngineService;
	private boolean stop = true;
	
	public FaceRun(LinkedBlockingQueue<BufferedImage> queue,String groupType,FaceEngineService faceEngineService) {
		this.queue = queue;
		this.groupType = groupType;
		this.faceEngineService = faceEngineService;
	}
	
	@Override
	public void run(){ 
		while(stop) {
			toDo();
		} 
	} 
	
	private void toDo(){
		try { 
			BufferedImage data = queue.take();//.poll(2, TimeUnit.SECONDS);// 有数据时直接从队列的队首取走，无数据时阻塞，在2s内有数据，取走，超过2s还没数据，返回失败
			if (hasFace(data)){  
				drowFace(data);
				checkAndSend(data);
			} 
			data.flush();
		} catch (Exception e) {
			e.printStackTrace();
			log.debug("图片 人脸 识别 异常");
		}
	} 
	
	/** 
	 * 检查图片，如果识别到人员则发送到前端  
	 */
	private void checkAndSend(BufferedImage data) throws IOException{
		//log.debug("到人员脸库,进行人脸识别!");
		List<FaceSearchResult> usersInDb = faceEngineService.findUsersByFaces(data,Long.valueOf(groupType));
		if (CollectionUtil.isEmpty(usersInDb)) return; 
		
		FaceMessage msg = new FaceMessage();
		ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
		Thumbnails.of(data).scale(0.5).outputFormat("jpg").toOutputStream(stream2);
		msg.setImg(Base64.encode(stream2.toByteArray())); 
		stream2.close();
		
		String faceId = "";
		String similar = "";
		for(FaceSearchResult search : usersInDb){ 
			faceId +=search.getFaceId()+",";
			similar += search.getSimilarValue()+",";
		}
		//msg.setFaceIds(CollectionUtil.join(usersInDb.stream().map(user -> user.getFaceId()).collect(Collectors.toList()),","));
		msg.setFaceIds(faceId);
		msg.setSimilars(similar);
		OldWebSocketServer.sendInfo(new Gson().toJson(msg),groupType); 
//		//测试
		/*FaceMessage msg = new FaceMessage();
		ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
		Thumbnails.of(data).scale(0.5).outputFormat("jpg").toOutputStream(stream2);
		msg.setImg(Base64.encode(stream2.toByteArray())); 
		stream2.close();
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) { 
			e.printStackTrace();
		} 
	 
		msg.setFaceIds("1135360052417400832,1135360052471926784,1135360052216074240");
		msg.setSimilars("99,98,97");
		OldWebSocketServer.sendInfo(new Gson().toJson(msg),screenName);*/
	}
	
	class FaceMessage{
		private String img;
		private String faceIds;
		private String similars;
		public String getImg() {
			return img;
		}
		public void setImg(String img) {
			this.img = img;
		}
		public String getFaceIds() {
			return faceIds;
		}
		public void setFaceIds(String faceIds) {
			this.faceIds = faceIds;
		}
		public String getSimilars() {
			return similars;
		}
		public void setSimilars(String similars) {
			this.similars = similars;
		} 
		
	}
	/** 
	 * 检查图片，是否有人脸
	 */
	private boolean hasFace(BufferedImage data){
		if(data == null) return false;
		if(OldWebSocketServer.canSend(groupType)) return false;
		return faceEngineService.whetherHasFaces(data);
	}
	/** 
	 * 在图片上画出人脸框
	 */
	private void drowFace(BufferedImage data)throws IOException{
		faceEngineService.drowFace(data); 
		zipAndSend(data);
	}
	/** 
	 * 压缩图片并发送到前端
	 */
	private void zipAndSend(BufferedImage data){ 
		ByteBuffer buf = img2Buffer(data);
		if(buf != null){ 
			OldWebSocketServer.sendByteBuffer(buf,groupType);	
		}
	}
	private ByteBuffer img2Buffer(BufferedImage data){ 
		try(ByteArrayOutputStream stream2 = new ByteArrayOutputStream();){ 
			Thumbnails.of(data).scale(0.5).outputFormat("jpg").toOutputStream(stream2); 
			return ByteBuffer.wrap(stream2.toByteArray());
		}catch (IOException e){
			e.printStackTrace();
		}
		return null;
	}
	
}